package net.lab1024.sa.admin.module.business.aps.service;

import lombok.extern.slf4j.Slf4j;
import net.lab1024.sa.admin.module.business.aps.domain.optaplanner.Resource;
import net.lab1024.sa.admin.module.business.aps.domain.optaplanner.ScheduleSolution;
import net.lab1024.sa.admin.module.business.aps.domain.optaplanner.Task;
import net.lab1024.sa.admin.module.business.aps.domain.vo.ApsScheduleResultVO;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * APS转换服务
 * 将OptaPlanner解决方案转换为前端展示格式
 *
 * @Author 1024创新实验室
 * @Date 2025-01-28
 * @Wechat zhuoda1024
 * @Email lab1024@163.com
 * @Copyright <a href="https://1024lab.net">1024创新实验室</a>
 */
@Slf4j
@Service
public class ApsConvertService {

    /**
     * 将ScheduleSolution转换为ApsScheduleResultVO
     */
    public ApsScheduleResultVO convertToResultVO(ScheduleSolution solution) {
        if (solution == null) {
            return null;
        }

        ApsScheduleResultVO resultVO = new ApsScheduleResultVO();
        
        // 基本信息
        resultVO.setSolutionName(solution.getSolutionName());
        resultVO.setScheduleStartTime(solution.getScheduleStartTime());
        resultVO.setScheduleEndTime(solution.getScheduleEndTime());
        resultVO.setTotalTaskCount(solution.getTotalTaskCount());
        resultVO.setAssignedTaskCount(solution.getAssignedTaskCount());
        resultVO.setUnassignedTaskCount(solution.getUnassignedTaskCount());
        resultVO.setResourceUtilization(solution.getResourceUtilization());
        resultVO.setFeasible(solution.isFeasible());
        resultVO.setScore(solution.getScore() != null ? solution.getScore().toString() : "未计算");
        
        // 转换任务分配信息
        if (solution.getTaskList() != null) {
            List<ApsScheduleResultVO.TaskAssignmentVO> taskAssignments = solution.getTaskList().stream()
                    .map(this::convertToTaskAssignmentVO)
                    .collect(Collectors.toList());
            resultVO.setTaskAssignments(taskAssignments);
        }
        
        // 转换资源使用情况
        if (solution.getResourceList() != null) {
            List<ApsScheduleResultVO.ResourceUsageVO> resourceUsages = solution.getResourceList().stream()
                    .map(resource -> convertToResourceUsageVO(resource, solution.getTaskList()))
                    .collect(Collectors.toList());
            resultVO.setResourceUsages(resourceUsages);
        }
        
        // 转换时间线数据
        List<ApsScheduleResultVO.TimelineItemVO> timelineItems = convertToTimelineItems(solution);
        resultVO.setTimelineItems(timelineItems);
        
        return resultVO;
    }

    /**
     * 转换任务为TaskAssignmentVO
     */
    private ApsScheduleResultVO.TaskAssignmentVO convertToTaskAssignmentVO(Task task) {
        ApsScheduleResultVO.TaskAssignmentVO vo = new ApsScheduleResultVO.TaskAssignmentVO();
        
        vo.setTaskId(task.getTaskId());
        vo.setTaskName(task.getTaskName());
        vo.setDescription(task.getDescription());
        vo.setDuration(task.getDuration());
        vo.setPriority(task.getPriority());
        vo.setPredecessorTaskIds(task.getPredecessorTaskIds());
        
        // 分配信息
        boolean assigned = task.getAssignedResource() != null && task.getStartTimeSlot() != null;
        vo.setAssigned(assigned);
        
        if (assigned) {
            vo.setAssignedResourceId(task.getAssignedResource().getResourceId());
            vo.setAssignedResourceName(task.getAssignedResource().getResourceName());
            vo.setStartTime(task.getStartTimeSlot().getStartTime());
            vo.setEndTime(task.getEndTime());
            vo.setStatus("已分配");
        } else {
            vo.setStatus("未分配");
        }
        
        return vo;
    }

    /**
     * 转换资源使用情况
     */
    private ApsScheduleResultVO.ResourceUsageVO convertToResourceUsageVO(Resource resource, List<Task> taskList) {
        ApsScheduleResultVO.ResourceUsageVO vo = new ApsScheduleResultVO.ResourceUsageVO();
        
        vo.setResourceId(resource.getResourceId());
        vo.setResourceName(resource.getResourceName());
        vo.setResourceType(resource.getResourceType());
        vo.setCapacity(resource.getCapacity());
        
        // 计算分配给该资源的任务
        List<Task> assignedTasks = taskList.stream()
                .filter(task -> task.getAssignedResource() != null && 
                               task.getAssignedResource().getResourceId().equals(resource.getResourceId()))
                .collect(Collectors.toList());
        
        vo.setAssignedTaskCount(assignedTasks.size());
        vo.setUtilizationRate(resource.getCapacity() > 0 ? 
                (double) assignedTasks.size() / resource.getCapacity() : 0.0);
        
        // 转换工作时间段
        List<ApsScheduleResultVO.WorkPeriodVO> workPeriods = assignedTasks.stream()
                .filter(task -> task.getStartTimeSlot() != null)
                .map(this::convertToWorkPeriodVO)
                .collect(Collectors.toList());
        vo.setWorkPeriods(workPeriods);
        
        return vo;
    }

    /**
     * 转换工作时间段
     */
    private ApsScheduleResultVO.WorkPeriodVO convertToWorkPeriodVO(Task task) {
        ApsScheduleResultVO.WorkPeriodVO vo = new ApsScheduleResultVO.WorkPeriodVO();
        
        vo.setTaskId(task.getTaskId());
        vo.setTaskName(task.getTaskName());
        vo.setStartTime(task.getStartTimeSlot().getStartTime());
        vo.setEndTime(task.getEndTime());
        vo.setDuration(task.getDuration());
        
        return vo;
    }

    /**
     * 转换时间线数据
     */
    private List<ApsScheduleResultVO.TimelineItemVO> convertToTimelineItems(ScheduleSolution solution) {
        List<ApsScheduleResultVO.TimelineItemVO> timelineItems = new ArrayList<>();
        
        if (solution.getTaskList() == null) {
            return timelineItems;
        }
        
        // 为每个已分配的任务创建时间线项目
        solution.getTaskList().stream()
                .filter(task -> task.getAssignedResource() != null && task.getStartTimeSlot() != null)
                .forEach(task -> {
                    ApsScheduleResultVO.TimelineItemVO item = new ApsScheduleResultVO.TimelineItemVO();
                    
                    item.setId("task_" + task.getTaskId());
                    item.setGroup(task.getAssignedResource().getResourceName());
                    item.setContent(task.getTaskName());
                    item.setStart(task.getStartTimeSlot().getStartTime());
                    item.setEnd(task.getEndTime());
                    item.setType("range");
                    item.setPriority(task.getPriority());
                    
                    // 根据优先级设置样式
                    if (task.getPriority() != null) {
                        if (task.getPriority() >= 8) {
                            item.setClassName("high-priority");
                        } else if (task.getPriority() >= 5) {
                            item.setClassName("medium-priority");
                        } else {
                            item.setClassName("low-priority");
                        }
                    }
                    
                    // 设置标题（鼠标悬停显示）
                    item.setTitle(String.format("任务: %s\n优先级: %d\n持续时间: %d分钟\n资源: %s",
                            task.getTaskName(),
                            task.getPriority(),
                            task.getDuration(),
                            task.getAssignedResource().getResourceName()));
                    
                    timelineItems.add(item);
                });
        
        return timelineItems;
    }

    /**
     * 生成甘特图数据
     */
    public Map<String, Object> generateGanttData(ScheduleSolution solution) {
        Map<String, Object> ganttData = new HashMap<>();
        
        if (solution == null || solution.getTaskList() == null) {
            return ganttData;
        }
        
        List<Map<String, Object>> tasks = new ArrayList<>();
        List<Map<String, Object>> links = new ArrayList<>();
        
        // 转换任务数据
        solution.getTaskList().forEach(task -> {
            Map<String, Object> taskData = new HashMap<>();
            taskData.put("id", task.getTaskId());
            taskData.put("text", task.getTaskName());
            taskData.put("duration", task.getDuration());
            taskData.put("priority", task.getPriority());
            
            if (task.getStartTimeSlot() != null) {
                taskData.put("start_date", task.getStartTimeSlot().getStartTime().toString());
                taskData.put("end_date", task.getEndTime().toString());
            }
            
            if (task.getAssignedResource() != null) {
                taskData.put("resource", task.getAssignedResource().getResourceName());
            }
            
            tasks.add(taskData);
            
            // 处理前置任务关系
            if (task.getPredecessorTaskIds() != null && !task.getPredecessorTaskIds().isEmpty()) {
                String[] predecessorIds = task.getPredecessorTaskIds().split(",");
                for (String predecessorId : predecessorIds) {
                    Map<String, Object> link = new HashMap<>();
                    link.put("id", "link_" + predecessorId + "_" + task.getTaskId());
                    link.put("source", Long.parseLong(predecessorId.trim()));
                    link.put("target", task.getTaskId());
                    link.put("type", "0"); // finish-to-start
                    links.add(link);
                }
            }
        });
        
        ganttData.put("data", tasks);
        ganttData.put("links", links);
        
        return ganttData;
    }

    /**
     * 生成资源负载图数据
     */
    public Map<String, Object> generateResourceLoadData(ScheduleSolution solution) {
        Map<String, Object> loadData = new HashMap<>();
        
        if (solution == null || solution.getResourceList() == null) {
            return loadData;
        }
        
        List<String> resourceNames = new ArrayList<>();
        List<Double> utilizationRates = new ArrayList<>();
        List<Integer> taskCounts = new ArrayList<>();
        
        solution.getResourceList().forEach(resource -> {
            resourceNames.add(resource.getResourceName());
            
            // 计算该资源的任务数量
            int taskCount = (int) solution.getTaskList().stream()
                    .filter(task -> task.getAssignedResource() != null && 
                                   task.getAssignedResource().getResourceId().equals(resource.getResourceId()))
                    .count();
            
            taskCounts.add(taskCount);
            
            // 计算利用率
            double utilizationRate = resource.getCapacity() > 0 ? 
                    (double) taskCount / resource.getCapacity() * 100 : 0.0;
            utilizationRates.add(utilizationRate);
        });
        
        loadData.put("resourceNames", resourceNames);
        loadData.put("utilizationRates", utilizationRates);
        loadData.put("taskCounts", taskCounts);
        
        return loadData;
    }
}